package com.efast.dmom.aps.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.efast.dmom.aps.bean.AnalysisBean;
import com.efast.dmom.aps.bean.Bom;
import com.efast.dmom.aps.bean.BomItem;
import com.efast.dmom.aps.bean.Part;
import com.efast.dmom.aps.bean.PlanOrder;
import com.efast.dmom.aps.bean.PlanOrderPartAnalysisResult;
import com.efast.dmom.aps.bean.PlanOrderPartAnalysisResultItem;
import com.efast.dmom.aps.bean.ResultBean;
import com.efast.dmom.aps.constant.ServiceConstants;
import com.efast.dmom.aps.datahandlers.PartInventoryDataHandler;
import com.efast.dmom.aps.datahandlers.PlanOrderDataHandler;
import com.efast.dmom.aps.entity.PartEntity;
import com.efast.dmom.aps.entity.PlanOrderEntity;
import com.efast.dmom.aps.entity.PlanOrderPartAnalysisResultEntity;
import com.efast.dmom.aps.entity.PlanOrderPartAnalysisResultItemEntity;
import com.efast.dmom.aps.service.BomService;
import com.efast.dmom.aps.service.PartService;
import com.efast.dmom.aps.service.PlanOrderPartAnalysisResultService;
import com.efast.dmom.aps.service.PlanOrderPartHomogeneityAnalysisService;
import com.efast.dmom.aps.util.TimeUtil;

@Service
public class PlanOrderPartHomogeneityAnalysisServiceImpl implements PlanOrderPartHomogeneityAnalysisService {

	@Autowired
	private PlanOrderDataHandler planOrderDataHandler;

	@Autowired
	private PartInventoryDataHandler partInventoryDataHandler;

	@Autowired
	private BomService bomService;

	@Autowired
	private PartService partService;

	@Autowired
	private PlanOrderPartAnalysisResultService planOrderPartAnalysisResultService;

	private Map<String, Integer> inventoryMap = new HashMap<String, Integer>();

//	private Map<String, Integer> beforeInventoryMap = new HashMap<String, Integer>();
	
	private List<Bom> bomList = new ArrayList<Bom>();

	private List<Part> partList = new ArrayList<Part>();

	@Override
	public ResultBean realizeHomogeneityAnalysis(List<PlanOrder> listData) {
		ResultBean resultBean = new ResultBean(true, ' ');
		List<PlanOrder> planOrderList = new ArrayList<PlanOrder>();
		// Determines whether the incoming plan order is empty
		if (listData != null && listData.size() > 0) {
			for (PlanOrder planOrder : listData) {
				if (planOrder.getInnerData().getOrderStatus() == ServiceConstants.APS_PLAN_ORDER_STATUS_BROADCAST
						|| planOrder.getInnerData().getOrderStatus() == ServiceConstants.APS_PLAN_ORDER_STATUS_FREEZE) {
					resultBean.setSuccess(false);
					resultBean.setMessage("存在冻结和下发状态的计划工单!");
					return resultBean;
				}
			}
			// sort plan order by plan offline date and priority
			sortPlanOrderByOfflineDataAndPriority(listData, planOrderList);
		} else {
			// Obtain unissued and frozen scheduled work orders
			List<PlanOrder> orderList = planOrderDataHandler.getUnbroadcastAndUnFreezePlanOrders();
			if (orderList == null || orderList.size() == 0) {
				resultBean.setSuccess(false);
				resultBean.setMessage("不存在可分析的计划工单!");
				return resultBean;
			}
			for (PlanOrder data : orderList) {
				planOrderList.add(data);
			}
		}
		// get the quantity of part in stock
		inventoryMap = partInventoryDataHandler.getPartInventory();
		// get all Bom and BomItem
		bomList = bomService.getAllBom();
		// get all part
		partList = partService.getAllPart();
		if (partList == null || partList.size() <= 0) {
			resultBean.setSuccess(false);
			resultBean.setMessage("物料数据为空!");
			return resultBean;
		}
		if (bomList == null || bomList.size() <= 0) {
			resultBean.setSuccess(false);
			resultBean.setMessage("Bom数据为空!");
			return resultBean;
		}
		planOrderPartAnalysisResultService.deleteAll();
		// traverse planOrderList
		planOrderAnalysis(planOrderList, resultBean);
		return resultBean;
	}

	// plan work order analysis
	public ResultBean planOrderAnalysis(List<PlanOrder> planOrderList, ResultBean resultBean) {
		// create a PlanOrderPartAnalysisResult list
		List<PlanOrderPartAnalysisResult> analysisResultList = new ArrayList<PlanOrderPartAnalysisResult>();

		for (PlanOrder planOrderData : planOrderList) {

			PlanOrderEntity planOrderEntity = planOrderData.getInnerData();

			Part part = getPartByPartNoAndPartRevision(planOrderEntity.getPartNo(), planOrderEntity.getPartRevision());
			if (part == null || part.getInnerData() == null) {
				resultBean.setSuccess(false);
				resultBean.setMessage("工单号为" + planOrderEntity.getOrderNumber() + "的计划工单不存在可分析的part数据!");
				return resultBean;
			}
			PlanOrderPartAnalysisResult planOrderPartAnalysisResult = createPlanOrderPartAnalysisResult(
					planOrderEntity);

			// Inventory before analysis
//			beforeInventoryMap.clear();
//			for (Map.Entry<String, Integer> entry : inventoryMap.entrySet()) {
//				beforeInventoryMap.put(entry.getKey(), entry.getValue());
//			}
			AnalysisBean analysisBean = analyzeByPart(planOrderEntity, part);

			if (!analysisBean.isSuccess()) {
				resultBean.setSuccess(false);
				resultBean.setMessage("计划工单号为" + planOrderEntity.getOrderNumber() + "的计划工单分析过程中未在物料数据中找到"
						+ analysisBean.getMessage() + "类型的物料数据!");
				return resultBean;
			}

			if (analysisBean.isFlag()) {
				planOrderPartAnalysisResult.getInnerData().setAnalysisResult("齐套");
//				inventoryMap.clear();
//				for (Map.Entry<String, Integer> entry : beforeInventoryMap.entrySet()) {
//					inventoryMap.put(entry.getKey(), entry.getValue());
//				}
			} else {
				planOrderPartAnalysisResult.getInnerData().setAnalysisResult("不齐套");
			}

			List<PlanOrderPartAnalysisResultItem> resultItemList = analysisBean.getResultItemList();
//          不要删，可能要用
//			if (resultItemList != null && resultItemList.size() > 0) {
//				// Merge the same type of part data
//				for (int i = 0; i < resultItemList.size(); i++) {
//					for (int j = i + 1; j < resultItemList.size(); j++) {
//						if (resultItemList.get(i).getInnerData().getPartNo()
//								.equals(resultItemList.get(j).getInnerData().getPartNo())
//								&& resultItemList.get(i).getInnerData().getPartRevision()
//										.equals(resultItemList.get(j).getInnerData().getPartRevision())) {
//							resultItemList.get(i).getInnerData()
//									.setPartDemandQty(resultItemList.get(i).getInnerData().getPartDemandQty()
//											+ resultItemList.get(j).getInnerData().getPartDemandQty());
//							if (resultItemList.get(i).getInnerData().getAlternatePartAnslysisResult().equals("库存足够")
//									&& resultItemList.get(j).getInnerData().getAlternatePartAnslysisResult()
//											.equals("库存足够")) {
//								resultItemList.get(i).getInnerData().setAlternatePartAnslysisResult("库存足够");
//							} else {
//								resultItemList.get(i).getInnerData().setAlternatePartAnslysisResult("库存不足");
//							}
//							resultItemList.remove(j);
//						}
//					}
//				}
//				for (PlanOrderPartAnalysisResultItem data : resultItemList) {
//					for (Map.Entry<String, Integer> entry : inventoryMap.entrySet()) {
//						if (entry.getKey().equals(
//								data.getInnerData().getPartNo() + "-" + data.getInnerData().getPartRevision())) {
//							data.getInnerData().setPartInventoryQty(entry.getValue());
//							if (entry.getValue() >= data.getInnerData().getPartDemandQty()) {
//								data.getInnerData().setPartRemainingDemandQty(
//										entry.getValue() - data.getInnerData().getPartDemandQty());
//								double qty = entry.getValue() - data.getInnerData().getPartDemandQty();
//								inventoryMap.put(entry.getKey(), (int) qty);
//							} else {
//								data.getInnerData().setPartRemainingDemandQty(0);
//								inventoryMap.put(entry.getKey(), 0);
//							}
//						}
//					}
//				}
//			}

			planOrderPartAnalysisResult.setResultItemList(resultItemList);
			analysisResultList.add(planOrderPartAnalysisResult);
		}
		// save the results of integrity analysis
		planOrderPartAnalysisResultService.save(analysisResultList);
		resultBean.setSuccess(true);
		resultBean.setMessage("分析成功!");
		return resultBean;
	}

	// Analyze part of planned work order
	public AnalysisBean analyzeByPart(PlanOrderEntity planOrderEntity, Part part) {
		// ResultBean - auxiliary calculation
		AnalysisBean analysisBean = new AnalysisBean();
		analysisBean.setFlag(true);
		analysisBean.setSuccess(true);

		List<PlanOrderPartAnalysisResultItem> resultItemList = new ArrayList<PlanOrderPartAnalysisResultItem>();

		analysisBean.setResultItemList(resultItemList);

		traversePart(analysisBean, planOrderEntity.getQuantity(), part);
		return analysisBean;
	}

	// Walk through the bom under part
	public AnalysisBean traversePart(AnalysisBean analysisBean, double qty, Part part) {
		PartEntity partEntity = part.getInnerData();

		List<PlanOrderPartAnalysisResultItem> resultItemList = analysisBean.getResultItemList();

		PlanOrderPartAnalysisResultItem planOrderPartAnalysisResultItem = new PlanOrderPartAnalysisResultItem();

		PlanOrderPartAnalysisResultItemEntity planOrderPartAnalysisResultItemEntity = new PlanOrderPartAnalysisResultItemEntity();

		planOrderPartAnalysisResultItem.setInnerData(planOrderPartAnalysisResultItemEntity);

		planOrderPartAnalysisResultItemEntity.setPartId(partEntity.getId());
		planOrderPartAnalysisResultItemEntity.setPartNo(partEntity.getPartNo());
		planOrderPartAnalysisResultItemEntity.setPartRevision(partEntity.getPartRevision());
		planOrderPartAnalysisResultItemEntity.setPartName(partEntity.getName());
		planOrderPartAnalysisResultItemEntity.setPartType(partEntity.getType());
		planOrderPartAnalysisResultItemEntity.setPartUom(partEntity.getUom());
		planOrderPartAnalysisResultItemEntity.setPartDemandQty(qty);

		for (Map.Entry<String, Integer> entry : inventoryMap.entrySet()) {
			if (entry.getKey().equals(partEntity.getPartNo() + "-" + partEntity.getPartRevision())) {
				planOrderPartAnalysisResultItemEntity.setPartInventoryQty(entry.getValue());
			}
		}
		if (planOrderPartAnalysisResultItemEntity.getPartInventoryQty() >= planOrderPartAnalysisResultItemEntity
				.getPartDemandQty()) {
			// Quantity in stock minus quantity in demand
			planOrderPartAnalysisResultItemEntity
					.setPartRemainingDemandQty(planOrderPartAnalysisResultItemEntity.getPartInventoryQty()
							- planOrderPartAnalysisResultItemEntity.getPartDemandQty());
			planOrderPartAnalysisResultItemEntity.setPartAnslysisResult("库存足够");
			planOrderPartAnalysisResultItemEntity.setFinalAnslysisResult("齐套");
			resultItemList.add(planOrderPartAnalysisResultItem);
			analysisBean.setResultItemList(resultItemList);

			for (Map.Entry<String, Integer> entry : inventoryMap.entrySet()) {
				if (entry.getKey().equals(partEntity.getPartNo() + "-" + partEntity.getPartRevision())) {
					double inventoryQty = planOrderPartAnalysisResultItemEntity.getPartInventoryQty()
							- planOrderPartAnalysisResultItemEntity.getPartDemandQty();
					inventoryMap.put(entry.getKey(), (int) inventoryQty);
				}
			}
			return analysisBean;
		} else {
			for (Map.Entry<String, Integer> entry : inventoryMap.entrySet()) {
				if (entry.getKey().equals(partEntity.getPartNo() + "-" + partEntity.getPartRevision())) {
					inventoryMap.put(entry.getKey(), 0);
				}
			}
			double remainQty = planOrderPartAnalysisResultItemEntity.getPartDemandQty()
					- planOrderPartAnalysisResultItemEntity.getPartInventoryQty();
			planOrderPartAnalysisResultItemEntity.setPartRemainingDemandQty(0);
			planOrderPartAnalysisResultItemEntity.setPartAnslysisResult("库存不足");
			planOrderPartAnalysisResultItemEntity.setFinalAnslysisResult("不齐套");
			resultItemList.add(planOrderPartAnalysisResultItem);
			analysisBean.setResultItemList(resultItemList);
			// get bom under part
			Bom bom = getBomByPart(part);
			if (bom == null || bom.getInnerData() == null) {
				analysisBean.setFlag(false);
				analysisBean.setResultItemList(resultItemList);
				return analysisBean;
			}
			traverseBom(bom, analysisBean, remainQty);
		}
		return analysisBean;
	}

	public AnalysisBean traverseBom(Bom bom, AnalysisBean analysisBean, double qty) {
		List<BomItem> bomItemList = bom.getItems();
		if (bomItemList != null && bomItemList.size() > 0) {
			for (BomItem itemData : bomItemList) {
				Part part = getPartByPartNoAndPartRevision(itemData.getInnerData().getPartNo(),
						itemData.getInnerData().getPartRevision());
				if (part == null || part.getInnerData() == null) {
					analysisBean.setSuccess(false);
					analysisBean.setMessage(
							itemData.getInnerData().getPartNo() + "-" + itemData.getInnerData().getPartRevision());
					return analysisBean;
				}
				if (analysisBean.getResultItemList() != null && analysisBean.getResultItemList().size() > 0) {
					Boolean flag = true;
					for (PlanOrderPartAnalysisResultItem data : analysisBean.getResultItemList()) {
						if (data.getInnerData().getPartNo().equals(part.getInnerData().getPartNo()) && data
								.getInnerData().getPartRevision().equals(part.getInnerData().getPartRevision())) {
							flag = false;
							analysisBean.setFlag(false);
							break;
						}
					}
					if (!flag) {
						continue;
					}
				}
				traversePart(analysisBean, qty * itemData.getInnerData().getQty(), part);
			}
		}
		return analysisBean;
	}

	// get a bom
	public Bom getBomByPart(Part part) {
		for (Bom bom : bomList) {
			if (bom.getInnerData().getName().equals(part.getInnerData().getBomName())
					&& bom.getInnerData().getRevision().equals(part.getInnerData().getBomRevision())) {
				return bom;
			}
		}
		return null;
	}

	// get a part
	public Part getPartByPartNoAndPartRevision(String partNo, String partRevision) {
		for (Part partData : partList) {
			if (partNo.equals(partData.getInnerData().getPartNo())
					&& partRevision.equals(partData.getInnerData().getPartRevision())) {
				return partData;
			}
		}
		return null;
	}

	// create a planOrderPartAnalysisResult
	public PlanOrderPartAnalysisResult createPlanOrderPartAnalysisResult(PlanOrderEntity planOrderEntity) {

		PlanOrderPartAnalysisResult partAnalysisResult = new PlanOrderPartAnalysisResult();

		PlanOrderPartAnalysisResultEntity planOrderPartAnalysisResultEntity = new PlanOrderPartAnalysisResultEntity();

		planOrderPartAnalysisResultEntity.setName(planOrderEntity.getOrderNumber() + "的分析结果");
		planOrderPartAnalysisResultEntity.setPlanOrderId(planOrderEntity.getId());
		planOrderPartAnalysisResultEntity.setPlanOrderNo(planOrderEntity.getOrderNumber());
		planOrderPartAnalysisResultEntity.setPartNo(planOrderEntity.getPartNo());
		planOrderPartAnalysisResultEntity.setPartDesc(planOrderEntity.getPartDesc());
		planOrderPartAnalysisResultEntity.setPartRevision(planOrderEntity.getPartRevision());
		planOrderPartAnalysisResultEntity.setQty(planOrderEntity.getQuantity());
		planOrderPartAnalysisResultEntity.setPlanOfflineDate(planOrderEntity.getPlanOfflineDate());
		planOrderPartAnalysisResultEntity.setPriority(planOrderEntity.getPriority());
		planOrderPartAnalysisResultEntity.setAnalysisTime(TimeUtil.getLocalDateTime());

		partAnalysisResult.setInnerData(planOrderPartAnalysisResultEntity);

		return partAnalysisResult;
	}

	// sort plan order by plan offline date and priority
	public List<PlanOrder> sortPlanOrderByOfflineDataAndPriority(List<PlanOrder> listData,
			List<PlanOrder> planOrderList) {
		Collections.sort(listData, new Comparator<PlanOrder>() {
			@Override
			public int compare(PlanOrder order1, PlanOrder order2) {
				PlanOrderEntity entity1 = order1.getInnerData();
				PlanOrderEntity entity2 = order2.getInnerData();
				if (entity1 == null) {
					return -1;
				}
				if (entity2 == null) {
					return -1;
				}
				if (entity1.getPlanOfflineDate() == null) {
					return -1;
				}
				if (entity2.getPlanOfflineDate() == null) {
					return -1;
				}
				if (entity1.getPlanOfflineDate().isBefore(entity2.getPlanOfflineDate()))
					return -1;
				else if (entity1.getPlanOfflineDate().isAfter(entity2.getPlanOfflineDate())) {
					return 1;
				} else if (entity1.getPlanOfflineDate().equals(entity2.getPlanOfflineDate())) {
					if (entity1.getPriority() > entity2.getPriority()) {
						return -1;
					}
					if (entity1.getPriority() < entity2.getPriority()) {
						return 1;
					}
				}
				return 0;
			}

		});
		for (PlanOrder planOrder : listData) {
			planOrderList.add(planOrder);
		}
		return planOrderList;
	}

}
